package com.quiz.bis.service.impl;

import com.quiz.bis.domain.dto.*;
import com.quiz.bis.domain.model.ProcessedText;
import com.quiz.bis.domain.model.QuestionFingerprint;
import com.quiz.bis.mapper.QuestionFingerprintMapper;
import com.quiz.bis.service.IQuestionDuplicateCheckService;
import com.quiz.bis.service.ITextSimilarityService;
import com.quiz.bis.util.text.CosineSimilarity;
import com.quiz.bis.util.text.TextPreprocessor;
import com.quiz.common.core.domain.R;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 题目查重服务实现
 */
@Service
@RequiredArgsConstructor
public class QuestionDuplicateCheckServiceImpl implements IQuestionDuplicateCheckService {

    private final QuestionFingerprintMapper fingerprintMapper;
    private final TextSimilarityServiceImpl similarityService;
    private final TextPreprocessor textPreprocessor;

    @Override
    @Transactional
    public R<Long> submitQuestion(QuestionSubmitDto dto) {
        // 预处理文本并计算特征
        ProcessedText processedText = textPreprocessor.preprocess(dto.getContent());
        long simHash = similarityService.computeSimHash(dto.getContent(), processedText);

        // 保存题目指纹
        QuestionFingerprint fingerprint = new QuestionFingerprint();
        fingerprint.setTitle(dto.getTitle());
        fingerprint.setTypeId(dto.getTypeId());
        fingerprint.setContent(dto.getContent());
        fingerprint.setContentText(processedText.getCleanText());
        fingerprint.setAnalysis(dto.getAnalysis());
        fingerprint.setAnalysisText(
                textPreprocessor.cleanHtml(dto.getAnalysis()));
        fingerprint.setDifficult(dto.getDifficult());
        fingerprint.setRemark(dto.getRemark());
        fingerprint.setStatus(1); // 默认启用
        fingerprint.setSimHash(simHash);

        fingerprintMapper.insert(fingerprint);

        return R.ok(fingerprint.getId());
    }

    @Override
    public R<List<QuestionDuplicateResult>> checkDuplicate(QuestionDuplicateCheckDto dto) {
        List<QuestionDuplicateResult> results = similarityService.findSimilarQuestions(
                dto.getContent(), dto.getThreshold());
        return R.ok(results);
    }

    @Override
    public R<List<QuestionDuplicateResult>> batchCheckDuplicate(List<QuestionDuplicateCheckDto> dtos) {
        List<QuestionDuplicateResult> allResults = dtos.stream()
                .flatMap(dto -> checkDuplicate(dto).getData().stream())
                .collect(Collectors.toList());
        return R.ok(allResults);
    }

    @Override
    public R<QuestionDuplicateDetail> getDuplicateDetail(Long questionId, Long targetId) {
        QuestionFingerprint question = fingerprintMapper.selectById(questionId);
        QuestionFingerprint target = fingerprintMapper.selectById(targetId);

        if (question == null || target == null) {
            return R.fail("题目不存在");
        }

        ProcessedText processed1 = textPreprocessor.preprocess(question.getContent());
        ProcessedText processed2 = textPreprocessor.preprocess(target.getContent());

        // 计算各项相似度
        double textSimilarity = CosineSimilarity.computeCosineSimilarity(
                processed1.getWords(), processed2.getWords());
        double formulaSimilarity = similarityService.calculateFormulaSimilarity(
                processed1.getFormulas(), processed2.getFormulas());
        double imageSimilarity = similarityService.calculateImageSimilarity(
                processed1.getImageIds(), processed2.getImageIds());
        double tableSimilarity = similarityService.calculateTableSimilarity(
                processed1.getTables(), processed2.getTables());

        // 构建详细结果
        QuestionDuplicateDetail detail = new QuestionDuplicateDetail();
        detail.setQuestionId(questionId);
        detail.setTargetId(targetId);
        detail.setTitleSimilarity(textSimilarity);
        detail.setContentSimilarity(textSimilarity);
        detail.setFormulaSimilarity(formulaSimilarity);
        detail.setImageSimilarity(imageSimilarity);
        detail.setTableSimilarity(tableSimilarity);
        detail.setOverallSimilarity(
                0.4 * textSimilarity +
                        0.3 * formulaSimilarity +
                        0.15 * imageSimilarity +
                        0.15 * tableSimilarity);

        return R.ok(detail);
    }
}